using UnityEngine;
using UnityEditor;

[ExecuteInEditMode] // 使脚本在编辑模式下运行
public class HexGridGizmos : MonoBehaviour
{
    [Header("蜂窝网格设置")]
    public float hexSize = 10f; // 单个蜂窝的大小（对边距离）

    public float gridRange = 150f;       // 从中心向各方向延伸的距离（总范围300m×300m）
    public Color hexColor = Color.white; // 蜂窝线条颜色
    public float lineThickness = 1f;     // 线条粗细

    [Header("点阵设置")]
    public bool enableDotGrid = false;        // 是否启用点阵绘制
    public int dotsPerHex = 5;                // 每个六边形区域内的点数量（每边）
    public float dotSize = 0.2f;              // 点的大小
    public Color dotColor = Color.yellow;     // 点的颜色
    public bool useShaderRendering = false;   // 是否使用Shader渲染（高性能模式，需要运行时）
    [Range(0f, 1f)]
    public float dotDensity = 1f;             // 点密度（0-1，用于随机分布）

    // 正六边形的几何参数
    private float hexRadius;          // 外接圆半径
    private float horizontalDistance; // 水平方向间距
    private float verticalDistance;   // 垂直方向间距

    private void OnEnable()
    {
        // 计算蜂窝的几何参数
        hexRadius = hexSize / Mathf.Sqrt(3);
        horizontalDistance = 1.5f * hexRadius;
        verticalDistance = hexSize;
    }

    // 在Scene视图中绘制Gizmos
    private void OnDrawGizmos()
    {
        CalculateGridParameters();

        Gizmos.color = hexColor;
        DrawHexGrid();

        // 绘制边界框
        Gizmos.color = Color.cyan;
        Gizmos.DrawWireCube(Vector3.zero, new Vector3(gridRange * 2, 0, gridRange * 2));
    }

    // 使用Handles绘制更清晰的线条（适合编辑模式）
    private void OnSceneGUI()
    {
        CalculateGridParameters();

        Handles.color = hexColor;
        Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual; // 确保线条在物体前面显示

        // 保存当前矩阵状态
        using (new Handles.DrawingScope(Matrix4x4.identity))
        {
            DrawHexGridWithHandles();
        }
    }

    private void CalculateGridParameters()
    {
        hexRadius = hexSize / Mathf.Sqrt(3);
        horizontalDistance = 1.5f * hexRadius;
        verticalDistance = hexSize;
    }

    // 使用Gizmos绘制蜂窝网格
    private void DrawHexGrid()
    {
        int halfRows = Mathf.FloorToInt(gridRange / verticalDistance) + 1;
        int halfCols = Mathf.FloorToInt(gridRange / horizontalDistance) + 1;

        // 遍历所有行和列
        for (int row = -halfRows; row <= halfRows; row++)
        {
            for (int col = -halfCols; col <= halfCols; col++)
            {
                // 计算蜂窝中心
                Vector3 center = CalculateHexCenter(row, col);

                // 检查是否在范围内
                if (IsPointInRange(center))
                {
                    // 绘制六边形
                    DrawHexagon(center);
                    
                    // 绘制点阵
                    if (enableDotGrid && !useShaderRendering)
                    {
                        DrawDotsInHexagon(center);
                    }
                }
            }
        }
    }

    // 使用Handles绘制蜂窝网格（线条更清晰）
    private void DrawHexGridWithHandles()
    {
        int halfRows = Mathf.FloorToInt(gridRange / verticalDistance) + 1;
        int halfCols = Mathf.FloorToInt(gridRange / horizontalDistance) + 1;

        // 保存当前线条粗细
        // float originalLineWidth = Handles.;
        // Handles.lineWidth = lineThickness;

        // 遍历所有行和列
        for (int row = -halfRows; row <= halfRows; row++)
        {
            for (int col = -halfCols; col <= halfCols; col++)
            {
                // 计算蜂窝中心
                Vector3 center = CalculateHexCenter(row, col);

                // 检查是否在范围内
                if (IsPointInRange(center))
                {
                    // 绘制六边形
                    DrawHexagonWithHandles(center);
                    
                    // 绘制点阵（使用Handles版本）
                    if (enableDotGrid && !useShaderRendering)
                    {
                        DrawDotsInHexagonWithHandles(center);
                    }
                }
            }
        }

        // 恢复线条粗细
        // Handles.lineWidth = originalLineWidth;
    }

    // 计算蜂窝中心位置
    private Vector3 CalculateHexCenter(int row, int col)
    {
        float x = col * horizontalDistance;

        // 奇数行偏移，实现蜂窝排列
        if (row % 2 != 0)
        {
            x += horizontalDistance / 2;
        }

        float z = row * verticalDistance;

        return new Vector3(x, 0, z);
    }

    // 检查点是否在网格范围内
    private bool IsPointInRange(Vector3 point)
    {
        return Mathf.Abs(point.x) <= gridRange && Mathf.Abs(point.z) <= gridRange;
    }

    // 绘制单个六边形（Gizmos版）
    private void DrawHexagon(Vector3 center)
    {
        Vector3[] vertices = new Vector3[6];

        // 计算六边形的6个顶点
        for (int i = 0; i < 6; i++)
        {
            float angle = 2 * Mathf.PI / 6 * (i + 0.5f); // 角度偏移，使上下边水平
            float x = center.x + hexRadius * Mathf.Cos(angle);
            float z = center.z + hexRadius * Mathf.Sin(angle);
            vertices[i] = new Vector3(x, 0, z);
        }

        // 绘制六边形的边
        for (int i = 0; i < 6; i++)
        {
            int j = (i + 1) % 6;
            Gizmos.DrawLine(vertices[i], vertices[j]);
        }
    }

    // 绘制单个六边形（Handles版）
    private void DrawHexagonWithHandles(Vector3 center)
    {
        Vector3[] vertices = new Vector3[6];

        // 计算六边形的6个顶点
        for (int i = 0; i < 6; i++)
        {
            float angle = 2 * Mathf.PI / 6 * (i + 0.5f); // 角度偏移，使上下边水平
            float x = center.x + hexRadius * Mathf.Cos(angle);
            float z = center.z + hexRadius * Mathf.Sin(angle);
            vertices[i] = new Vector3(x, 0, z);
        }

        // 绘制六边形的边
        for (int i = 0; i < 6; i++)
        {
            int j = (i + 1) % 6;
            Handles.DrawLine(vertices[i], vertices[j]);
        }
    }

    // 绘制单个六边形内的点阵（Gizmos版）
    private void DrawDotsInHexagon(Vector3 center)
    {
        // 使用规则网格分布，使用确定性算法避免闪烁
        float innerRadius = hexRadius * 0.866f; // 内切圆半径约为外接圆的0.866倍
        int gridSize = dotsPerHex;
        float stepSize = innerRadius / gridSize;
        
        // 使用六边形中心位置作为随机种子，确保每个六边形的点分布是确定的
        int seed = Mathf.RoundToInt(center.x * 1000 + center.z * 1000);
        UnityEngine.Random.State oldState = UnityEngine.Random.state;
        UnityEngine.Random.InitState(seed);
        
        for (int u = -gridSize; u <= gridSize; u++)
        {
            for (int v = -gridSize; v <= gridSize; v++)
            {
                // 使用确定性随机来决定是否绘制这个点
                if (UnityEngine.Random.value > dotDensity) continue;

                // 在六边形坐标系中生成点
                float x = u * stepSize;
                float z = v * stepSize;
                
                Vector3 point = center + new Vector3(x, 0, z);
                
                // 检查点是否在六边形内
                if (IsPointInHexagon(point, center))
                {
                    Gizmos.DrawSphere(point, dotSize);
                }
            }
        }
        
        UnityEngine.Random.state = oldState;
    }

    // 绘制单个六边形内的点阵（Handles版）
    private void DrawDotsInHexagonWithHandles(Vector3 center)
    {
        // 使用规则网格分布，使用确定性算法避免闪烁
        float innerRadius = hexRadius * 0.866f; // 内切圆半径
        int gridSize = dotsPerHex;
        float stepSize = innerRadius / gridSize;
        
        // 使用六边形中心位置作为随机种子，确保每个六边形的点分布是确定的
        int seed = Mathf.RoundToInt(center.x * 1000 + center.z * 1000);
        UnityEngine.Random.State oldState = UnityEngine.Random.state;
        UnityEngine.Random.InitState(seed);
        
        for (int u = -gridSize; u <= gridSize; u++)
        {
            for (int v = -gridSize; v <= gridSize; v++)
            {
                // 使用确定性随机来决定是否绘制这个点
                if (UnityEngine.Random.value > dotDensity) continue;

                float x = u * stepSize;
                float z = v * stepSize;
                
                Vector3 point = center + new Vector3(x, 0, z);
                
                // 检查点是否在六边形内
                if (IsPointInHexagon(point, center))
                {
                    Handles.DrawSolidDisc(point, Vector3.up, dotSize);
                }
            }
        }
        
        UnityEngine.Random.state = oldState;
    }

    // 检查点是否在六边形内（使用更简单高效的方法）
    private bool IsPointInHexagon(Vector3 point, Vector3 hexCenter)
    {
        Vector3 localPoint = point - hexCenter;
        float distance = Mathf.Sqrt(localPoint.x * localPoint.x + localPoint.z * localPoint.z);
        
        // 先检查是否在外接圆内（快速剔除）
        if (distance > hexRadius * 1.01f) // 添加小容差
            return false;

        // 使用角度和距离检查点是否在六边形内
        // 六边形可以看作6个三角形的组合
        float angle = Mathf.Atan2(localPoint.z, localPoint.x);
        
        // 将角度规范化到[-π, π]，然后调整到[0, 2π]
        if (angle < 0) angle += 2 * Mathf.PI;
        
        // 计算点所在扇形的索引（0-5）
        float sectorAngle = 2 * Mathf.PI / 6;
        float normalizedAngle = angle + Mathf.PI / 6; // 调整角度，使第一个扇区从0开始
        if (normalizedAngle >= 2 * Mathf.PI) normalizedAngle -= 2 * Mathf.PI;
        
        int sector = Mathf.FloorToInt(normalizedAngle / sectorAngle);
        sector = sector % 6;
        
        // 计算该扇形的边界角度
        float sectorStartAngle = sector * sectorAngle - Mathf.PI / 6;
        float sectorEndAngle = (sector + 1) * sectorAngle - Mathf.PI / 6;
        
        // 计算点到该扇形对应边的距离
        // 边的方向是垂直于从中心到边的中点的向量
        float midAngle = (sectorStartAngle + sectorEndAngle) / 2;
        Vector3 edgeNormal = new Vector3(Mathf.Cos(midAngle + Mathf.PI / 2), 0, Mathf.Sin(midAngle + Mathf.PI / 2));
        
        // 计算从中心到边的距离（六边形的内切圆半径）
        float edgeDistance = hexRadius * 0.8660254f; // cos(30°) = √3/2 ≈ 0.866
        
        // 计算点到六边形中心的投影到边法向量的距离
        float distToEdge = Vector3.Dot(localPoint, edgeNormal);
        
        return distToEdge <= edgeDistance;
    }

    // 兼容方法：为了保持接口一致
    private void DrawDotGrid()
    {
        // 这个方法不再需要，因为点阵已经在DrawHexGrid中绘制了
    }

    private void DrawDotGridWithHandles()
    {
        // 这个方法不再需要，因为点阵已经在DrawHexGridWithHandles中绘制了
    }
}